home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / DEMOS / PUMPSRC.ZIP / DPMIDVT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-27  |  8.7 KB  |  268 lines

  1. /* ------------------------ DPMIDVT.C --------------------------- */
  2. /* DPMI interface code to DemoVT v1.5 and higher.                 */
  3. /* Written bye Jare of Iguana in 1994.                            */
  4. /* -------------------------------------------------------------- */
  5. /* Thanks to Yann for supplying all those specs, and also to Tran */
  6. /* of nothing for getting me into this wonderful world of PMode.  */
  7. /* -------------------------------------------------------------- */
  8. /* This code will compile under Watcom C++ 9.5. I think it should */
  9. /* work also with other versions and under other 32 bit compilers */
  10. /* but I haven't bothered to test.                                */
  11. /* -------------------------------------------------------------- */
  12. /* You will find some general purpose DPMI code here. Use it!     */
  13. /* Especially that RealModeMem variable.                          */
  14. /* That variable is not necessary under DOS4GW, because the first */
  15. /* megabyte is directly accesible using the default data seg. But */
  16. /* I have included it to make this code fully portable to other,  */
  17. /* more hostile environments.                                     */
  18. /* You might need to translate it to assembly, but that should be */
  19. /* easy. After all, it's your job! :)                             */
  20. /* -------------------------------------------------------------- */
  21.  
  22. #include <stdlib.h>
  23.  
  24. #include "pump.h"
  25.  
  26. typedef struct SDPMI_rminfo {       // Real mode registers for the DPMI
  27.     dword EDI;                      // translation API.
  28.     dword ESI;
  29.     dword EBP;
  30.     dword _reserved;
  31.     dword EBX;
  32.     dword EDX;
  33.     dword ECX;
  34.     dword EAX;
  35.     word  flags;
  36.     word  ES, DS, FS, GS;
  37.     word  IP, CS, SP, SS;
  38. } TDPMI_RealModeInfo;
  39.  
  40. #define FLAGS_CARRY  0x0001         // To check flags above.
  41. #define FLAGS_PARITY 0x0004
  42. #define FLAGS_AUX    0x0010
  43. #define FLAGS_ZERO   0x0040
  44. #define FLAGS_SIGN   0x0080
  45.  
  46.  
  47.  
  48. static TDPMI_RealModeInfo  DPMI_rmi;
  49.  
  50. static union  REGS  rmregs;
  51. static struct SREGS rmsregs;
  52.  
  53. static void DPMI_RealModeCall(void) {
  54.     DPMI_rmi.SS = DPMI_rmi.SP = 0;    // DPMI host will provide its own stack.
  55.     rmregs.h.bh  = 0;                 // Do not reset PIC or A20 gate.
  56.     rmregs.w.cx  = 0;                 // 0 words of parameters on the stack.
  57.     rmregs.x.edi = FP_OFF(&DPMI_rmi); // Real mode info.
  58.     rmsregs.es   = FP_SEG(&DPMI_rmi);
  59.     int386x(0x31, &rmregs, &rmregs, &rmsregs);
  60. }
  61.  
  62. static void DPMI_RealModeInt(int i) {
  63.     rmregs.w.ax = 0x300;
  64.     rmregs.h.bl = i;
  65.     DPMI_RealModeCall();
  66. }
  67.  
  68. static void DPMI_RealModeProc(word seg, word off) {
  69. /*
  70.     rmregs.w.ax = 0x301;
  71.     DPMI_rmi.CS = seg;
  72.     DPMI_rmi.IP = off;
  73.     DPMI_RealModeCall();
  74.  
  75.     ********************************************************
  76.     WARNING: DOS4GW v1.8 bundled with WATCOM C++ 9.5 doesn't
  77.     seem to suuport the above call (at least I didn't get it
  78.     to work), so we used a wierd scheme to emulate it.
  79.     JCAB - 2/94
  80.     DOS4GW 1.95 doesn't work either. What's going on?
  81.     Jare - 3/94
  82.     ********************************************************
  83. */
  84.  
  85.     dword _far *vectable = (dword _far *)RealModeMem;
  86.     dword oldvec4 = vectable[4];
  87.     dword oldvec6 = vectable[6];
  88.     dword oldvec7 = vectable[7];
  89.  
  90.        // None of these interrupts should occur during normal operation.
  91.        // but the way to do would be to allocate Real Mode Memory and place
  92.        // the call there. INT 4 still should be used. I hate this!
  93.     vectable[4] = 6*4+1; // Address of INT6 vector.
  94.     vectable[6] = (long)0x9A00 + ((long)off<<16);   // FAR CALL [seg:off]
  95.     vectable[7] = (long)seg    + ((long)0xCF<<16);  // + IRET
  96.     DPMI_RealModeInt(4);
  97.  
  98.     vectable[4] = oldvec4;
  99.     vectable[6] = oldvec6;
  100.     vectable[7] = oldvec7;
  101.  
  102. }
  103.  
  104. static void _far * DPMI_MapRealModeSegment(word rmseg) {
  105.  
  106.     rmregs.x.eax = 0x0002;
  107.     rmregs.x.ebx = (dword)rmseg;
  108.     int386(0x31, &rmregs, &rmregs);
  109.  
  110. //    if (rmregs.x.cflag & FLAGS_CARRY)
  111. //        return NULL;
  112. //    else
  113.         return MK_FP(rmregs.w.ax, 0);
  114. }
  115.  
  116. static byte _far *DPMI_MapMemory(dword baseaddr, dword len) {
  117.     word selector;
  118.  
  119.     rmregs.x.eax = 0x0000;          // Allocate descriptor.
  120.     rmregs.x.ecx = 1;               // One descriptor.
  121.     int386(0x31, &rmregs, &rmregs);
  122. //    if (rmregs.x.cflag & FLAGS_CARRY)
  123. //        return NULL;
  124.     selector = rmregs.w.ax;
  125.  
  126.     rmregs.x.eax = 0x0007;          // Set selector base address.
  127.     rmregs.x.ebx = (dword)selector;
  128.     rmregs.x.edx = (dword)((word)baseaddr);
  129.     rmregs.x.ecx = (dword)(baseaddr >> 16);
  130.     int386(0x31, &rmregs, &rmregs);
  131. //    if (!(rmregs.x.cflag & FLAGS_CARRY))
  132.     {
  133.         rmregs.x.eax = 0x0009;      // Set descriptor access rights.
  134.         rmregs.x.ebx = (dword)selector;
  135.         rmregs.x.ecx = 0xCF93;
  136.         int386(0x31, &rmregs, &rmregs);
  137. //        if (!(rmregs.x.cflag & FLAGS_CARRY))
  138.         {
  139.             rmregs.x.eax = 0x0008;      // Set segment limit.
  140.             rmregs.x.ebx = (dword)selector;
  141.             rmregs.x.edx = (dword)((word)len);
  142.             rmregs.x.ecx = (dword)(len >> 16);
  143.             int386(0x31, &rmregs, &rmregs);
  144.             if (!(rmregs.x.cflag & FLAGS_CARRY))
  145.                 return (MK_FP(selector, 0));    // Everything OK.
  146.             // puts("Error setting limit");
  147.         }
  148. //        else
  149.             ;//puts("Error setting rights.");
  150.     }
  151. //    else
  152.         ;//puts("Error setting base address.");
  153.  
  154.       // Something went wrong, so we free the selector.
  155.     rmregs.x.eax = 0x0001;          // Free selector.
  156.     rmregs.x.ebx = (dword)selector;
  157.     int386(0x31, &rmregs, &rmregs);
  158.       // We don't care about errors freeing the selector. Can't do
  159.       // much about it I guess.
  160.     return NULL;
  161. }
  162.  
  163. // -------------------------------------------------------
  164.  
  165.  // -------------------------------------------------------
  166.  
  167. byte     _far *RealModeMem   = NULL;
  168. dword          DVTAppIdFound = 0;
  169. volatile TDVTInfo _far *DVTInfo       = NULL;
  170.  
  171.  
  172. int DVT_Init(void) {
  173.     int present;
  174.     byte _far *p;
  175.  
  176.     if (DVTInfo != NULL)        // Already initialized?
  177.         return 1;
  178.     DPMI_rmi.EAX = 0x5654;      // DemoVT magic numbers.
  179.     DPMI_rmi.EBX = 0x5472;
  180.     DPMI_rmi.ECX = 0x6163;
  181.     DPMI_rmi.EDI = 0;
  182.     DPMI_rmi.ES  = 0;
  183.     DPMI_RealModeInt(0x2F);     // Perform call.
  184.  
  185.     present = (   (word)DPMI_rmi.EAX == 0       // Complex check.
  186.                && (word)DPMI_rmi.EBX == 0x3F17
  187.                && (word)DPMI_rmi.ECX == 0x1343);
  188.     if (present) {                              // Allocate far pointer.
  189.         p = DPMI_MapMemory(0, 1024*1024-1);
  190.         if (p != NULL) {
  191.             word _far *g;
  192.             RealModeMem = p;
  193.             DVTAppIdFound = (dword)((DPMI_rmi.ES << 4)
  194.                             + (word)(DPMI_rmi.EDI));
  195.             g = (word _far *) (p + DVTAppIdFound - 4);
  196.             DVTInfo = (TDVTInfo _far *)(p + g[0] + (g[1] << 4));
  197.         }
  198.     }
  199.     return present;
  200. }
  201.  
  202. void DVT_CallDemoVT(int command) {
  203.     if (DVTInfo == NULL                 // Not initialized?
  204.         || command < 0 || command > 3)  // or invalid parameter?
  205.         return;
  206.     DPMI_rmi.EAX = command;
  207.     DPMI_RealModeProc(DVTInfo->entryPointAXSeg, DVTInfo->entryPointAXOff);
  208. }
  209.  
  210. dword DVT_GetTickCounter(void) {
  211.     if (DVTInfo == NULL)    // Not initialized?
  212.         return 0;
  213.     return DVTInfo->tickCounter;
  214. }
  215.  
  216. void DVT_WaitForStart(void) {
  217.     if (DVTInfo == NULL)    // Not initialized?
  218.         return;
  219.     DVTInfo->tickCounter = 0;
  220.     while (DVTInfo->tickCounter < 25)
  221.         DVT_CallMusic();
  222.     DVTInfo->tickCounter = 0;
  223. }
  224.  
  225. void DVT_JumpPos(byte pattern, byte note) {
  226.     if (DVTInfo == NULL)    // Not initialized?
  227.         return;
  228.     DVTInfo->jumpPosSeq  = pattern;
  229.     DVTInfo->jumpPosNote = note;
  230.     DVTInfo->jumpNewPos  = 1;
  231. }
  232.  
  233. byte DVT_GetSemaphore(byte nsem) {
  234.     if (DVTInfo == NULL)    // Not initialized?
  235.         return 0;
  236.     return DVTInfo->semaphores[nsem];
  237. }
  238.  
  239. void DVT_SetSemaphore(byte nsem, byte value) {
  240.     if (DVTInfo == NULL)    // Not initialized?
  241.         return;
  242.     DVTInfo->semaphores[nsem] = value;
  243. }
  244.  
  245. void DVT_MiddleSync(byte nsem, byte pattern, byte note) {
  246.     if (DVTInfo == NULL || nsem > 255)    // Not initialized or error?
  247.         return;
  248.  
  249.     if (nsem == 255 || DVT_GetSemaphore(nsem) == 0)
  250.         DVT_JumpPos(pattern, note);
  251.     while (nsem < 255 && DVT_GetSemaphore(nsem+1) == 0);
  252. }
  253.  
  254. byte DVT_GetSoundVolume(void) {
  255.     if (DVTInfo == NULL)    // Not initialized?
  256.         return 255;
  257.     return DVTInfo->soundVolume;
  258. }
  259.  
  260. void DVT_SetSoundVolume(byte vol) {
  261.     if (DVTInfo == NULL)    // Not initialized?
  262.         return;
  263.     DVTInfo->soundVolume = vol;
  264. }
  265.  
  266. /* ------------------------ DPMIDVT.C --------------------------- */
  267.  
  268.